{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": "tensor([[ 0.5000,  0.5000, -1.6094, -1.6094, -0.3927]])"
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from math import pi\n",
    "import kwarray\n",
    "import torch\n",
    "import numpy as np\n",
    "from mmdet.core.bbox.demodata import random_boxes\n",
    "from mmdet.models.roi_heads.bbox_heads.obb.obbox_head import OBBoxHead\n",
    "def regular_theta(theta, mode='180', start=-pi/2):\n",
    "    assert mode in ['360', '180']\n",
    "    cycle = 2 * pi if mode == '360' else pi\n",
    "\n",
    "    theta = theta - start\n",
    "    theta = theta % cycle\n",
    "    return theta + start\n",
    "\n",
    "def obb2delta(proposals, gt, theta_norm=True, means=(0., 0., 0., 0., 0.), stds=(1., 1., 1., 1., 1.)):\n",
    "    proposals = proposals.float()\n",
    "    gt = gt.float()\n",
    "    px = (proposals[..., 0] + proposals[..., 2]) * 0.5\n",
    "    py = (proposals[..., 1] + proposals[..., 3]) * 0.5\n",
    "    pw = proposals[..., 2] - proposals[..., 0]\n",
    "    ph = proposals[..., 3] - proposals[..., 1]\n",
    "    gx, gy, gw, gh, gtheta = gt.unbind(dim=-1)\n",
    "\n",
    "    dtheta1 = regular_theta(gtheta)\n",
    "    dtheta2 = regular_theta(gtheta + pi/2)\n",
    "    abs_dtheta1 = torch.abs(dtheta1)\n",
    "    abs_dtheta2 = torch.abs(dtheta2)\n",
    "\n",
    "    gw_regular = torch.where(abs_dtheta1 < abs_dtheta2, gw, gh)\n",
    "    gh_regular = torch.where(abs_dtheta1 < abs_dtheta2, gh, gw)\n",
    "    dtheta = torch.where(abs_dtheta1 < abs_dtheta2, dtheta1, dtheta2)\n",
    "    dx = (gx - px) / pw\n",
    "    dy = (gy - py) / ph\n",
    "    dw = torch.log(gw_regular / pw)\n",
    "    dh = torch.log(gh_regular / ph)\n",
    "\n",
    "    # if theta_norm:\n",
    "    #     dtheta /= 2 * pi\n",
    "    deltas = torch.stack([dx, dy, dw, dh, dtheta], dim=-1)\n",
    "\n",
    "    means = deltas.new_tensor(means).unsqueeze(0)\n",
    "    stds = deltas.new_tensor(stds).unsqueeze(0)\n",
    "    deltas = deltas.sub_(means).div_(stds)\n",
    "    return deltas\n",
    "obb2delta(torch.tensor([[0,0,100,100]]),torch.tensor([[100,100,20,20,-pi/8]]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "outputs": [
    {
     "data": {
      "text/plain": "tensor([[ 1.3179,  1.4083,  1.1869, -0.4343],\n        [ 1.1830, -0.9141, -0.8578,  0.6139],\n        [ 0.1219,  0.2479, -0.6154,  1.0037]])"
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = torch.randn((3,4))\n",
    "a"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "outputs": [],
   "source": [
    "def f(temp):\n",
    "    temp = temp.reshape(4,3)\n",
    "f(a)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "outputs": [
    {
     "data": {
      "text/plain": "torch.Size([9998])"
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "# from mmdet.datasets.pipelines.obb.base import pol\n",
    "a = torch.randn(100,100)\n",
    "a.unique().shape"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0  1  2  3  4  5  6  7]\n",
      " [ 8  9 10 11 12 13 14 15]\n",
      " [16 17 18 19 20 21 22 23]\n",
      " [24 25 26 27 28 29 30 31]]\n",
      "-135.0\n",
      "135.0\n",
      "-135.0\n",
      "135.0\n",
      "-135.0\n",
      "135.0\n",
      "-135.0\n",
      "135.0\n"
     ]
    },
    {
     "data": {
      "text/plain": "array([[  81.887375,  139.18317 ,  396.1709  ,  -90.      ,   45.      ],\n       [ 540.2537  ,  597.5495  ,  396.1709  ,  -90.      ,   45.      ],\n       [ 998.6201  , 1055.9158  ,  396.1709  ,  -90.      ,   45.      ],\n       [1456.9865  , 1514.2822  ,  396.1709  ,  -90.      ,   45.      ]],\n      dtype=float32)"
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from BboxToolkit.transforms import poly2obb\n",
    "import numpy as np\n",
    "temp = np.arange(32).reshape(4,8)\n",
    "print(temp)\n",
    "poly2obb(temp)/3.141592*180-90\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "dict_keys(['cls', 'content'])\n",
      "41.035343170166016\n",
      "-41.035343170166016\n",
      "22.520565032958984\n",
      "-112.52056503295898\n",
      "24.443954467773438\n",
      "-114.44395446777344\n",
      "23.36911392211914\n",
      "-113.36911392211914\n",
      "-0.0\n",
      "-90.0\n",
      "86.8201675415039\n",
      "-86.8201675415039\n",
      "24.443954467773438\n",
      "-114.44395446777344\n",
      "23.38521957397461\n",
      "-113.38521957397461\n",
      "15.350136756896973\n",
      "-105.35013675689697\n",
      "53.74616622924805\n",
      "-143.74616622924805\n",
      "87.27368927001953\n",
      "-87.27368927001953\n",
      "40.31410217285156\n",
      "-40.31410217285156\n"
     ]
    },
    {
     "data": {
      "text/plain": "array([[ 9.0155219e+02,  4.6610214e+01,  7.1589104e+01,  1.3549547e+01,\n        -7.1620172e-01],\n       [ 7.3950000e+02,  2.0700000e+02,  8.8972137e+01,  1.6154221e+01,\n        -1.9638540e+00],\n       [ 7.4361304e+02,  2.3605139e+02,  7.7877716e+01,  1.2083046e+01,\n        -1.9974234e+00],\n       [ 7.6099994e+02,  2.3699995e+02,  8.9598282e+01,  1.5752796e+01,\n        -1.9786639e+00],\n       [ 8.6000000e+02,  2.5350000e+02,  6.2999992e+01,  1.5999998e+01,\n        -1.5707960e+00],\n       [ 8.7844153e+02,  2.3244769e+02,  9.2246643e+01,  1.8027756e+01,\n        -1.5152974e+00],\n       [ 1.0007945e+03,  2.6345203e+02,  3.6249138e+01,  9.4347057e+00,\n        -1.9974234e+00],\n       [ 9.8912311e+02,  2.5971539e+02,  4.0311291e+01,  1.1163126e+01,\n        -1.9789450e+00],\n       [ 6.8017773e+02,  2.2535272e+02,  5.2886673e+01,  1.6223370e+01,\n        -1.8387064e+00],\n       [ 2.2900000e+02,  2.8100000e+02,  2.0321407e+01,  7.4189262e+00,\n        -2.5088434e+00],\n       [ 6.2148193e+02,  2.3011993e+02,  2.1023796e+01,  1.5981891e+01,\n        -1.5232129e+00],\n       [ 8.9550000e+02,  6.3000004e+01,  8.7226418e+01,  1.7791878e+01,\n        -7.0361370e-01]], dtype=float32)"
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import mmcv\n",
    "temp = mmcv.load('data/split_ss_dota1_0/train/annfiles/patch_annfile.pkl')\n",
    "print(temp.keys())\n",
    "temp = temp['content'][1]['ann']['bboxes']\n",
    "poly2obb(temp)\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/brother/anaconda3/envs/obbdetection/lib/python3.7/site-packages/torch/_tensor.py:490: UserWarning: non-inplace resize is deprecated\n",
      "  warnings.warn(\"non-inplace resize is deprecated\")\n"
     ]
    },
    {
     "data": {
      "text/plain": "tensor([3, 3, 3, 3, 3, 3, 3, 3])"
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "a = torch.arange(32).resize(8,4)\n",
    "a.argmax(-1)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[100.       100.        20.        20.         0.785398]]\n",
      "[[100.00000231  85.85786438 114.14213562 100.00000231  99.99999769\n",
      "  114.14213562  85.85786438  99.99999769]] (1, 8)\n",
      "****************************************************************************************************\n",
      "cv:angle: -45.0\n",
      "45.0\n",
      "[[100.00001  100.000015  20.        20.         0.785398]]\n",
      "****************************************************************************************************\n",
      "cv:angle: -45.0\n",
      "45.0\n"
     ]
    },
    {
     "data": {
      "text/plain": "array([[100.00001 ,  85.85788 , 114.14214 , 100.000015, 100.00001 ,\n        114.14215 ,  85.85787 , 100.000015]], dtype=float32)"
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as  plt\n",
    "import cv2\n",
    "from einops import rearrange\n",
    "pi=3.141592\n",
    "def poly2obb(polys):\n",
    "    # [-90 90)\n",
    "    order = polys.shape[:-1]\n",
    "    num_points = polys.shape[-1] // 2\n",
    "    polys = polys.reshape(-1, num_points, 2)\n",
    "    polys = polys.astype(np.float32)\n",
    "\n",
    "    obboxes = []\n",
    "    for poly in polys:\n",
    "        (x, y), (w, h), angle = cv2.minAreaRect(poly)\n",
    "        print('*'*100)\n",
    "        print('cv:angle:',angle)\n",
    "        # if angle==90:\n",
    "        #     angle=0\n",
    "        # if w>=h:\n",
    "        #     angle = angle\n",
    "        # else:\n",
    "        #     w,h = h,w\n",
    "        #     angle = -(90-angle)\n",
    "        if w >= h:\n",
    "            if angle==-90:\n",
    "                angle=90\n",
    "            angle = -angle\n",
    "        else:\n",
    "            w, h = h, w\n",
    "            angle = -90 - angle\n",
    "        print(angle)\n",
    "        theta = angle / 180 * pi\n",
    "        obboxes.append([x, y, w, h, theta])\n",
    "\n",
    "    if not obboxes:\n",
    "        obboxes = np.zeros((0, 5), dtype=np.float32)\n",
    "    else:\n",
    "        obboxes = np.array(obboxes, dtype=np.float32)\n",
    "    return obboxes.reshape(*order, 5)\n",
    "def obb2poly(obboxes):\n",
    "    center, w, h, theta = np.split(obboxes, (2, 3, 4), axis=-1)\n",
    "    Cos, Sin = np.cos(theta), np.sin(theta)\n",
    "\n",
    "    vector1 = np.concatenate(\n",
    "        [w/2 * Cos, -w/2 * Sin], axis=-1)\n",
    "    vector2 = np.concatenate(\n",
    "        [-h/2 * Sin, -h/2 * Cos], axis=-1)\n",
    "\n",
    "    point1 = center + vector1 + vector2\n",
    "    point2 = center + vector1 - vector2\n",
    "    point3 = center - vector1 - vector2\n",
    "    point4 = center - vector1 + vector2\n",
    "    return np.concatenate(\n",
    "        [point1, point2, point3, point4], axis=-1)\n",
    "a = np.array([[100,100,30,20,3.141592/6]])\n",
    "a = np.array([[100,100,20,20,pi/4]])\n",
    "print(a)\n",
    "b = obb2poly(a)\n",
    "print(b,b.shape)\n",
    "# print(b,b.shape)\n",
    "# # plt.plot(b.reshape(-1,2))\n",
    "# print(rearrange(b,'c (x y) -> (c y) x',x=2,c=1))\n",
    "# plt.plot(rearrange(b,'c (x y) -> (c y) x',x=2))\n",
    "\n",
    "print(poly2obb(obb2poly(a)))\n",
    "obb2poly(poly2obb((b)))"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[0.0369, 0.1768, 3.0519],\n",
      "        [8.2774, 0.0451, 0.6590],\n",
      "        [0.1829, 4.1193, 0.0205]])\n"
     ]
    },
    {
     "data": {
      "text/plain": "tensor([1.0885, 2.9938, 1.4409])"
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "import torch.nn.functional as F\n",
    "a = torch.randn(3,3)\n",
    "b = torch.randn(3,3)\n",
    "\n",
    "print(F.mse_loss(a,b,reduction='none'))\n",
    "F.mse_loss(a,b,reduction='none').mean(-1)\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "outputs": [
    {
     "data": {
      "text/plain": "tensor([-1.0000, -0.9986, -0.9945, -0.9877, -0.9781, -0.9659, -0.9511, -0.9336,\n        -0.9135, -0.8910, -0.8660, -0.8387, -0.8090, -0.7771, -0.7431, -0.7071,\n        -0.6691, -0.6293, -0.5878, -0.5446, -0.5000, -0.4540, -0.4067, -0.3584,\n        -0.3090, -0.2588, -0.2079, -0.1564, -0.1045, -0.0523,  0.0000,  0.0523,\n         0.1045,  0.1564,  0.2079,  0.2588,  0.3090,  0.3584,  0.4067,  0.4540,\n         0.5000,  0.5446,  0.5878,  0.6293,  0.6691,  0.7071,  0.7431,  0.7771,\n         0.8090,  0.8387,  0.8660,  0.8910,  0.9135,  0.9336,  0.9511,  0.9659,\n         0.9781,  0.9877,  0.9945,  0.9986])"
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dim = 60\n",
    "from math import pi\n",
    "# pi=3.141592\n",
    "# a = F.one_hot(torch.tensor(30),60)\n",
    "b = torch.arange(0,dim)\n",
    "std = b*pi/dim-pi/2\n",
    "torch.sin(std)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "outputs": [
    {
     "data": {
      "text/plain": "tensor([ 0.9945,  0.9986, -1.0000, -0.9986, -0.9945, -0.9877, -0.9781, -0.9659,\n        -0.9511, -0.9336, -0.9135, -0.8910, -0.8660, -0.8387, -0.8090, -0.7771,\n        -0.7431, -0.7071, -0.6691, -0.6293, -0.5878, -0.5446, -0.5000, -0.4540,\n        -0.4067, -0.3584, -0.3090, -0.2588, -0.2079, -0.1564, -0.1045, -0.0523,\n         0.0000,  0.0523,  0.1045,  0.1564,  0.2079,  0.2588,  0.3090,  0.3584,\n         0.4067,  0.4540,  0.5000,  0.5446,  0.5878,  0.6293,  0.6691,  0.7071,\n         0.7431,  0.7771,  0.8090,  0.8387,  0.8660,  0.8910,  0.9135,  0.9336,\n         0.9511,  0.9659,  0.9781,  0.9877])"
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "torch.sin(torch.roll(std,2,0))\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "outputs": [
    {
     "data": {
      "text/plain": "tensor([0.0000, 0.0523, 0.1045, 0.1564, 0.2079, 0.2588, 0.3090, 0.3584, 0.4067,\n        0.4540, 0.5000, 0.5446, 0.5878, 0.6293, 0.6691, 0.7071, 0.7431, 0.7771,\n        0.8090, 0.8387, 0.8660, 0.8910, 0.9135, 0.9336, 0.9511, 0.9659, 0.9781,\n        0.9877, 0.9945, 0.9986, 1.0000, 0.9986, 0.9945, 0.9877, 0.9781, 0.9659,\n        0.9511, 0.9336, 0.9135, 0.8910, 0.8660, 0.8387, 0.8090, 0.7771, 0.7431,\n        0.7071, 0.6691, 0.6293, 0.5878, 0.5446, 0.5000, 0.4540, 0.4067, 0.3584,\n        0.3090, 0.2588, 0.2079, 0.1564, 0.1045, 0.0523])"
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "temp = torch.arange(0, dim)\n",
    "std_w = temp * pi / dim\n",
    "torch.abs(torch.sin(std_w))\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "outputs": [
    {
     "data": {
      "text/plain": "torch.Size([3])"
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = torch.randn((3,4))\n",
    "a.unbind(-1)[0].shape"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "def delta2obb(proposals,\n",
    "              deltas,\n",
    "              dtheta,\n",
    "              theta_norm=True,\n",
    "              means=(0., 0., 0., 0., 0.),\n",
    "              stds=(1., 1., 1., 1., 1.),\n",
    "              wh_ratio_clip=16 / 1000):\n",
    "    means = deltas.new_tensor(means).repeat(1, deltas.size(1) // 4)\n",
    "    stds = deltas.new_tensor(stds).repeat(1, deltas.size(1) // 4)\n",
    "    # print(deltas.shape, stds.shape, means.shape)\n",
    "    denorm_deltas = deltas * stds + means\n",
    "    dx = denorm_deltas[:, 0::4]\n",
    "    dy = denorm_deltas[:, 1::4]\n",
    "    dw = denorm_deltas[:, 2::4]\n",
    "    dh = denorm_deltas[:, 3::4]\n",
    "    # dtheta = denorm_deltas[:, 4::5]\n",
    "    # if theta_norm:\n",
    "    #     dtheta *= 2 * pi\n",
    "    max_ratio = np.abs(np.log(wh_ratio_clip))\n",
    "    dw = dw.clamp(min=-max_ratio, max=max_ratio)\n",
    "    dh = dh.clamp(min=-max_ratio, max=max_ratio)\n",
    "    px = ((proposals[:, 0] + proposals[:, 2]) * 0.5).unsqueeze(1).expand_as(dx)\n",
    "    py = ((proposals[:, 1] + proposals[:, 3]) * 0.5).unsqueeze(1).expand_as(dy)\n",
    "    pw = (proposals[:, 2] - proposals[:, 0]).unsqueeze(1).expand_as(dw)\n",
    "    ph = (proposals[:, 3] - proposals[:, 1]).unsqueeze(1).expand_as(dh)\n",
    "    gx = px + pw * dx\n",
    "    gy = py + ph * dy\n",
    "    gw = pw * dw.exp()\n",
    "    gh = ph * dh.exp()\n",
    "    gtheta = dtheta\n",
    "    # gtheta = torch.argmax(angle_preds, dim=-1) * pi / 60 - pi / 2\n",
    "    dtheta1 = regular_theta(gtheta)  # (gtheta+pi/2)%pi - pi/2          # (n)\n",
    "    dtheta2 = regular_theta(gtheta + pi / 2)  # (gtheta+pi)% pi -pi/2    # (n)\n",
    "    abs_dtheta1 = torch.abs(dtheta1)\n",
    "    abs_dtheta2 = torch.abs(dtheta2)\n",
    "    dtheta = torch.where(abs_dtheta1 < abs_dtheta2, dtheta1,\n",
    "                         dtheta2)  # dtheta (n)     # (-pi/4,pi/4):gtheta (pi/4,pi/2):pi/2-gtheta (-pi/2,-pi/4): pi/2+gtheta  # 这里才最终得到所谓的\n",
    "    bboxes = torch.stack([gx, gy, gw, gh, gtheta.unsqueeze(-1)], dim=-1)\n",
    "    bboxes = regular_obb(bboxes)\n",
    "    return bboxes.squeeze(1)\n",
    "from math import pi\n",
    "delta2obb(torch.tensor([[90,90,100,100]]),torch.tensor([[0.1,0,0,0.2]]),pi/6,means=(0,0,0,0),stds=(1,1,1,1))\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}